/*
 * Brush.java
 *
 * Created on 4 June 2003, 11:47
 *
 * Copyright 2009 the Desert Labs Project (http://desertlabs.us)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package us.desertlabs.visuals;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Stroke;


/**
 * The {@link Brush} class is an immutable grouping of some graphics attributes
 * related to the act of painting. Specifically, a {@link Brush}
 * represents a specific set of one each of the following: a {@link Paint},
 * a {@link Composite}, and a {@link Stroke}.
 *
 * @author Brandon Franklin
 */
public class Brush {

    /** The {@link Composite} used by this {@link Brush} */
    private final Composite composite;

    /** The {@link Paint} used by this {@link Brush} */
    private final Paint paint;

    /** The {@link Stroke} used by this {@link Brush} */
    private final Stroke stroke;

    /**
     * Creates a new instance of {@link Brush} with the specified
     * attributes. Any parameters that are set to null will be configured to
     * suitable default values.
     *
     * @param paint the {@link Paint} attribute for this instance to use
     * @param composite the {@link Composite} attribute for this instance
     *        to use
     * @param stroke the {@link Stroke} attribute for this instance to
     *        use
     */
    public Brush(final Paint paint, final Composite composite, final Stroke stroke) {

        if (paint == null) {
            this.paint = Color.BLACK;
        }
        else {
            this.paint = paint;
        }

        if (composite == null) {
            this.composite = AlphaComposite.Src;
        }
        else {
            this.composite = composite;
        }

        if (stroke == null) {
            this.stroke = new BasicStroke();
        }
        else {
            this.stroke = stroke;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Brush other = (Brush) obj;
        if (composite == null) {
            if (other.composite != null) {
                return false;
            }
        }
        else if (!composite.equals(other.composite)) {
            return false;
        }
        if (paint == null) {
            if (other.paint != null) {
                return false;
            }
        }
        else if (!paint.equals(other.paint)) {
            return false;
        }
        if (stroke == null) {
            if (other.stroke != null) {
                return false;
            }
        }
        else if (!stroke.equals(other.stroke)) {
            return false;
        }
        return true;
    }

    /**
     * Returns the {@link Composite} used by this {@link Brush}.
     *
     * @return the {@link Composite} used by this {@link Brush}
     */
    public Composite getComposite() {
        return composite;
    }

    /**
     * Returns the {@link Paint} used by this {@link Brush}.
     *
     * @return the {@link Paint} used by this {@link Brush}
     */
    public Paint getPaint() {
        return paint;
    }

    /**
     * Returns the {@link Stroke} used by this {@link Brush}.
     *
     * @return the {@link Stroke} used by this {@link Brush}
     */
    public Stroke getStroke() {
        return stroke;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((composite == null) ? 0 : composite.hashCode());
        result = prime * result + ((paint == null) ? 0 : paint.hashCode());
        result = prime * result + ((stroke == null) ? 0 : stroke.hashCode());
        return result;
    }

    /**
     * Configures the supplied {@link Graphics2D} instance to use this
     * {@link Brush}.
     *
     * @param g the {@link Graphics2D} to be configured
     */
    public void useOn(final Graphics2D g) {
        g.setPaint(paint);
        g.setStroke(stroke);
        g.setComposite(composite);
    }

}
